#ifndef PARALLELFWD2_H_
#define PARALLELFWD2_H_

#include <map>
#include <set>
#include "../sff/siena/types.h"
#include "ompTypes.h"
#include <iostream>
#include "../../Common/Timer.h"
#include "../../Common/Consts.h"
#include <omp.h>
#include <string.h>

using namespace std;
using namespace siena;

class ParallelFwd2 {
public:

	/**
	 * Constructor
	 */
	ParallelFwd2();

	/**
	 * Destructor
	 */
	virtual ~ParallelFwd2();

	/**
	 * Config an interface by setting its predicate (the set of its filters)
	 */
	void ifConfig(int interfaceId, set<OMPFilter *> &filters);

	/**
	 * Call this after all interfaces have been set
	 */
	void consolidate();

	/**
	 * Processes the message included into the outbox.
	 * Stores the set of matching interfaces ids inside the outbox.
	 */
	void processMessage(OMPOutbox *outbox);

	/**
	 * Returns the statistics about processing time distribution
	 */
	void getStats(double *in, double *exec, double *res);

private:

	map<int, set<OMPFilter *> > hostFilters;

	int numFilters;
	int numInterfaces;
	bool consolidated; 						// True if the consolidate method has been called

	map<string_t, int> numConstraints;
        map<string_t, OMPType> nameType;                           // Name -> type of constraints with that name
	map<string_t, void *> nameConstraints;
	OMPInput2 input; 							// Pointer to the input

	bool *interfaces; 						// Pointer to the array of interfaces
	OMPFilterInfo *filtersInfos;	// Filter -> filtersInfo
	unsigned short *filtersCount; 						// Filter -> number of constraints satisfied

	double inputTime;
	double execTime;
	double resultsTime;

	inline bool prefix(char *s1, char *s2);
	inline bool substr(char *s1, char *s2);

	inline void evalConstraint(int constraintIndex, int attrId);
	inline int makeInput(OMPMessage *message);
	inline void computeResults(int maxConstr);
	inline void getMatchingInterfaces(set<int> &results);

	inline IntOMPConstraint2 *findIntConstraint(IntOMPConstraint2 *constraints, int numConstraints, OMPConstraint &constraint);
	inline StringOMPConstraint2 *findStringConstraint(StringOMPConstraint2 *constraints, int numConstraints, OMPConstraint &constraint);
	inline void buildIntConstraint(IntOMPConstraint2 *result, OMPConstraint &constraint, int filterId);
	inline void buildStringConstraint(StringOMPConstraint2 *result, OMPConstraint &constraint, int filterId);
};

#endif /* PARALLELFWD2_H_ */
